#pragma once

#include <string>
#include <vector>
#include <map>
#include <functional>

#if !defined(UINT8)
typedef unsigned char       UINT8;
#endif
#if !defined(INT32)
typedef signed int          INT32;
#endif
#if !defined(UINT32)
typedef unsigned int        UINT32;
#endif

#if defined(_WIN32)
#if defined(_WINDLL)
#define RPF_CLASS __declspec(dllexport)
#else
#if defined(_USE_RPF_DLL)
#define RPF_CLASS __declspec(dllimport)
#else
#define RPF_CLASS
#endif
#endif
#else
#define RPF_CLASS
#endif

class RPF_CLASS CResPkgFile
{
public:
    class ThisImpl;

    static const INT32 MAX_FILES = 256;
    static const UINT32 LEN_SIZE = sizeof(UINT32);
    static const UINT32 MAX_SUBNAME_LEN = 64;
    static const UINT32 LINE_LEN = MAX_SUBNAME_LEN + 4 * LEN_SIZE;
    typedef struct _FileUnit
    {
        int nReserved;
        std::wstring strSubName;
        int nLevel;
        std::vector<UINT8> vSource;
        std::vector<UINT8> vCompressed;
    } FileUnit;
protected:
    CResPkgFile();
    virtual ~CResPkgFile();
public:
    static CResPkgFile* Handle();
    static void Release();

    bool IsChanged();
    const std::wstring& GetPath();
    void SetPath(const std::wstring& strPath);
    const std::vector<FileUnit>& GetFiles();
    const std::map<std::wstring, UINT32>& GetFilesIndices();

    void New();
    void Open_Threaded(const std::wstring& strPath, const std::function<void(int, int, int)>& f);
    void Open(const std::wstring& strPath);
    void Close();
    void Save();
    int Insert(const std::wstring& strPath, int level, const std::wstring& strSubName, bool force = false);
    void Edit(const std::wstring& strOldSubName, int level, const std::wstring& strSubName);
    void Delete(const std::wstring& strSubName);
protected:
    static CResPkgFile* m_pInstance;

    bool m_bChanged = false;
    ThisImpl* m_pThis = nullptr;
};

